home *** CD-ROM | disk | FTP | other *** search
- /* Generic glyph/image implementation + display tables
- Copyright (C) 1994, 1995 Board of Trustees, University of Illinois
- Copyright (C) 1995 Tinker Systems
- Copyright (C) 1995 Ben Wing
- Copyright (C) 1995 Sun Microsystems
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: Not in FSF. */
-
- /* Written by Ben Wing and Chuck Thompson */
-
- #include <config.h>
- #include "lisp.h"
-
- #include "buffer.h"
- #include "device.h"
- #include "elhash.h"
- #include "faces.h"
- #include "frame.h"
- #include "glyphs-x.h" /* #### Should be glyphs.h. Need to abstract. */
- #include "objects.h"
- #include "redisplay.h"
- #include "window.h"
-
- Lisp_Object Qglyphp, Qimage, Qcontrib_p, Qbaseline;
-
- /* Qtext defined in general.c */
- Lisp_Object Qmono_pixmap, Qcolor_pixmap, Qcursor, Qsubwindow;
-
- Lisp_Object Vcurrent_display_table;
-
- Lisp_Object Vtruncation_glyph, Vcontinuation_glyph, Voctal_escape_glyph;
- Lisp_Object Vcontrol_arrow_glyph, Vinvisible_text_glyph, Vhscroll_glyph;
- Lisp_Object Vxemacs_logo;
-
- Lisp_Object Vthe_nothing_vector;
-
- Lisp_Object Q_file, Q_data;
-
- Lisp_Object Qicon;
-
- DEFINE_IMAGE_INSTANTIATOR_TYPE (nothing);
- Lisp_Object Qnothing;
- DEFINE_IMAGE_INSTANTIATOR_TYPE (string);
- /* Qstring defined in general.c */
- DEFINE_IMAGE_INSTANTIATOR_TYPE (formatted_string);
- Lisp_Object Qformatted_string;
-
- MAC_DEFINE (struct image_instantiator_methods *, mactemp_iitype_meth_or_given);
-
- struct image_instantiator_type_entry
- {
- Lisp_Object symbol;
- struct image_instantiator_methods *meths;
- };
-
- typedef struct image_instantiator_type_entry_dynarr_type
- {
- Dynarr_declare (struct image_instantiator_type_entry);
- } image_instantiator_type_entry_dynarr;
-
- image_instantiator_type_entry_dynarr *the_image_instantiator_type_entry_dynarr;
-
- Lisp_Object Vimage_instantiator_type_list;
-
- Lisp_Object Vimage_instance_type_list;
-
- Lisp_Object Vglyph_type_list;
-
- static Lisp_Object allocate_image_instance (Lisp_Object device);
- static int validate_image_instantiator (Lisp_Object instantiator,
- int no_error);
-
-
- /****************************************************************************
- * Image Instantiators *
- ****************************************************************************/
-
- static struct image_instantiator_methods *
- decode_image_instantiator_type (Lisp_Object type, int no_error)
- {
- int i;
-
- if (!SYMBOLP (type))
- {
- if (!no_error)
- CHECK_SYMBOL (type, 0);
- return 0;
- }
-
- for (i = 0; i < Dynarr_length (the_image_instantiator_type_entry_dynarr);
- i++)
- {
- if (EQ (type,
- Dynarr_at (the_image_instantiator_type_entry_dynarr, i).symbol))
- return Dynarr_at (the_image_instantiator_type_entry_dynarr, i).meths;
- }
-
- if (!no_error)
- signal_simple_error ("Invalid image-instantiator type", type);
-
- return 0;
- }
-
- static int
- valid_image_instantiator_type_p (Lisp_Object type)
- {
- if (decode_image_instantiator_type (type, 1))
- return 1;
- return 0;
- }
-
- DEFUN ("valid-image-instantiator-type-p", Fvalid_image_instantiator_type_p,
- Svalid_image_instantiator_type_p, 1, 1, 0,
- "Given an IMAGE-INSTANTIATOR-TYPE, return non-nil if it is valid.\n\
- Valid types are some subset of 'nothing, 'string, 'formatted-string, 'xpm,\n\
- 'xbm, 'xface, 'gif, 'jpeg, 'png, 'autodetect, and 'subwindow, depending\n\
- on how XEmacs was compiled.")
- (image_instantiator_type)
- Lisp_Object image_instantiator_type;
- {
- if (valid_image_instantiator_type_p (image_instantiator_type))
- return Qt;
- else
- return Qnil;
- }
-
- DEFUN ("image-instantiator-type-list", Fimage_instantiator_type_list,
- Simage_instantiator_type_list,
- 0, 0, 0,
- "Return a list of valid image-instantiator types.")
- ()
- {
- return Fcopy_sequence (Vimage_instantiator_type_list);
- }
-
- void
- add_entry_to_image_instantiator_type_list (Lisp_Object symbol,
- struct image_instantiator_methods *
- meths)
- {
- struct image_instantiator_type_entry entry;
-
- entry.symbol = symbol;
- entry.meths = meths;
- Dynarr_add (the_image_instantiator_type_entry_dynarr, entry);
- Vimage_instantiator_type_list =
- Fcons (symbol, Vimage_instantiator_type_list);
- }
-
- static Lisp_Object *
- get_image_conversion_list (Lisp_Object device_type)
- {
- return &decode_device_type (device_type, 0)->image_conversion_list;
- }
-
- DEFUN ("set-device-type-image-conversion-list",
- Fset_device_type_image_conversion_list,
- Sset_device_type_image_conversion_list, 2, 2, 0,
- "Set the image-conversion-list for devices of the given TYPE.\n\
- The image-conversion-list specifies how image instantiators that\n\
- are strings should be interpreted. Each element of the list should be\n\
- a list of two elements (a regular expression string and a vector) or\n\
- a list of three elements (the preceding two plus an integer index into\n\
- the vector). The string is converted to the vector associated with the\n\
- first matching regular expression. If a vector index is specified, the\n\
- string itself is substituted into that position in the vector.\n\
- \n\
- Note: The conversion above is applied when the image instantiator is\n\
- added to an image specifier, not when the specifier is actually\n\
- instantiated. Therefore, changing the image-conversion-list only affects\n\
- newly-added instantiators. Existing instantiators in glyphs and image\n\
- specifiers will not be affected.")
- (device_type, list)
- Lisp_Object device_type, list;
- {
- Lisp_Object tail;
- Lisp_Object *imlist = get_image_conversion_list (device_type);
-
- /* Check the list to make sure that it only has valid entries. */
-
- EXTERNAL_LIST_LOOP (tail, list)
- {
- Lisp_Object mapping = XCAR (tail);
-
- /* Mapping form should be (STRING VECTOR) or (STRING VECTOR INTEGER) */
- if (!CONSP (mapping) ||
- !CONSP (XCDR (mapping)) ||
- (!NILP (XCDR (XCDR (mapping))) &&
- (!CONSP (XCDR (XCDR (mapping))) ||
- !NILP (XCDR (XCDR (XCDR (mapping)))))))
- signal_simple_error ("Invalid mapping form", mapping);
- else
- {
- Lisp_Object exp = XCAR (mapping);
- Lisp_Object typevec = XCAR (XCDR (mapping));
- Lisp_Object pos = Qnil;
- Lisp_Object newvec;
- struct gcpro gcpro1;
-
- CHECK_STRING (exp, 0);
- CHECK_VECTOR (typevec, 1);
- if (!NILP (XCDR (XCDR (mapping))))
- {
- pos = XCAR (XCDR (XCDR (mapping)));
- CHECK_INT (pos, 0);
- if (XINT (pos) < 0 ||
- XINT (pos) >= vector_length (XVECTOR (typevec)))
- args_out_of_range_3
- (pos, Qzero, make_number
- (vector_length (XVECTOR (typevec)) - 1));
- }
-
- newvec = Fcopy_sequence (typevec);
- if (INTP (pos))
- vector_data (XVECTOR (newvec))[XINT (pos)] = exp;
- GCPRO1 (newvec);
- if (!validate_image_instantiator (newvec, 0))
- signal_simple_error ("Invalid image-conversion-list vector",
- typevec);
- UNGCPRO;
- }
- }
-
- *imlist = Fcopy_tree (list, Qt);
- return list;
- }
-
- DEFUN ("device-type-image-conversion-list", Fdevice_type_image_conversion_list,
- Sdevice_type_image_conversion_list, 1, 1, 0,
- "Return the image-conversion-list for devices of the given TYPE.\n\
- The image-conversion-list specifies how to interpret image string\n\
- instantiators for the specified device type. See\n\
- `set-device-type-image-conversion-list' for a description of its syntax.")
- (device_type)
- Lisp_Object device_type;
- {
- return Fcopy_tree (*get_image_conversion_list (device_type), Qt);
- }
-
- /* Process an string instantiator according to the image-conversion-list for
- DEVICE_TYPE. Returns a vector. */
-
- static Lisp_Object
- process_image_string_instantiator (Lisp_Object data, Lisp_Object device_type,
- int no_error)
- {
- Lisp_Object tail;
-
- LIST_LOOP (tail, *get_image_conversion_list (device_type))
- {
- Lisp_Object mapping = XCAR (tail);
- Lisp_Object exp = XCAR (mapping);
- Lisp_Object typevec = XCAR (XCDR (mapping));
-
- if (fast_string_match (exp, 0, data, 0, -1, no_error, 0) >= 0)
- {
- if (!NILP (XCDR (XCDR (mapping))))
- {
- int pos = XINT (XCAR (XCDR (XCDR (mapping))));
- Lisp_Object newvec = Fcopy_sequence (typevec);
- vector_data (XVECTOR (newvec))[pos] = data;
- return newvec;
- }
- else
- return typevec;
- }
- }
-
-
- /* Oh well. */
-
- return Qnil;
- }
-
- Lisp_Object
- find_keyword_in_vector_or_given (Lisp_Object vector, Lisp_Object keyword,
- Lisp_Object defalt)
- {
- Lisp_Object *elt;
- int instantiator_len;
-
- elt = vector_data (XVECTOR (vector));
- instantiator_len = vector_length (XVECTOR (vector));
-
- elt++;
- instantiator_len--;
-
- while (instantiator_len > 0)
- {
- if (EQ (elt[0], keyword))
- return elt[1];
- elt += 2;
- instantiator_len -= 2;
- }
-
- return defalt;
- }
-
- Lisp_Object
- find_keyword_in_vector (Lisp_Object vector, Lisp_Object keyword)
- {
- return find_keyword_in_vector_or_given (vector, keyword, Qnil);
- }
-
- int
- valid_string_p (Lisp_Object data, int no_error)
- {
- if (!STRINGP (data))
- {
- if (!no_error)
- CHECK_STRING (data, 0);
- return 0;
- }
-
- return 1;
- }
-
- int
- valid_int_p (Lisp_Object data, int no_error)
- {
- if (!INTP (data))
- {
- if (!no_error)
- CHECK_INT (data, 0);
- return 0;
- }
-
- return 1;
- }
-
- int
- file_or_data_must_be_present (Lisp_Object instantiator, int no_error)
- {
- if (NILP (find_keyword_in_vector (instantiator, Q_file)) &&
- NILP (find_keyword_in_vector (instantiator, Q_data)))
- {
- if (!no_error)
- signal_simple_error ("Must supply either :file or :data",
- instantiator);
- return 0;
- }
-
- return 1;
- }
-
- int
- data_must_be_present (Lisp_Object instantiator, int no_error)
- {
- if (NILP (find_keyword_in_vector (instantiator, Q_data)))
- {
- if (!no_error)
- signal_simple_error ("Must supply :data", instantiator);
- return 0;
- }
-
- return 1;
- }
-
- /* utility function useful in retrieving data from a file. */
-
- Lisp_Object
- make_string_from_file (Lisp_Object file)
- {
- int count = specpdl_depth ();
- Lisp_Object temp_buffer;
- struct gcpro gcpro1;
- Lisp_Object data;
-
- specbind (Qinhibit_quit, Qt);
- record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
- temp_buffer = Fget_buffer_create (build_string (" *pixmap conversion*"));
- GCPRO1 (temp_buffer);
- set_buffer_internal (XBUFFER (temp_buffer));
- Ferase_buffer (Fcurrent_buffer ());
- /* #### need to catch errors here */
- Finsert_file_contents_internal (file, Qnil, Qnil, Qnil, Qnil);
- data = Fbuffer_substring (Qnil, Qnil, Fcurrent_buffer ());
- unbind_to (count, Qnil);
- UNGCPRO;
- return data;
- }
-
- /* The following two functions are provided to make it easier for
- the normalize methods to work with keyword-value vectors.
- Hash tables are kind of heavyweight for this purpose.
- (If vectors were resizable, we could avoid this problem;
- but they're not.) An alternative approach that might be
- more efficient but require more work is to use a type of
- assoc-Dynarr and provide primitives for deleting elements out
- of it. (However, you'd also have to add an unwind-protect
- to make sure the Dynarr got freed in case of an error in
- the normalization process.) */
-
- Lisp_Object
- tagged_vector_to_alist (Lisp_Object vector)
- {
- Lisp_Object *elt = vector_data (XVECTOR (vector));
- int len = vector_length (XVECTOR (vector));
- Lisp_Object result = Qnil;
-
- assert (len & 1);
- for (len -= 2; len >= 1; len -= 2)
- result = Fcons (Fcons (elt[len], elt[len+1]), result);
-
- return result;
- }
-
- Lisp_Object
- alist_to_tagged_vector (Lisp_Object tag, Lisp_Object alist)
- {
- int len = 1 + 2 * XINT (Flength (alist));
- Lisp_Object *elt = alloca (len * sizeof (Lisp_Object));
- int i;
- Lisp_Object rest;
-
- i = 0;
- elt[i++] = tag;
- LIST_LOOP (rest, alist)
- {
- Lisp_Object pair = XCAR (rest);
- elt[i] = XCAR (pair);
- elt[i+1] = XCDR (pair);
- i += 2;
- }
-
- return Fvector (len, elt);
- }
-
- static int
- validate_image_instantiator (Lisp_Object instantiator, int no_error)
- {
- if (STRINGP (instantiator))
- return 1;
- else if (VECTORP (instantiator))
- {
- Lisp_Object *elt = vector_data (XVECTOR (instantiator));
- int instantiator_len = XVECTOR (instantiator)->size;
- struct image_instantiator_methods *meths;
- Lisp_Object already_seen = Qnil;
- struct gcpro gcpro1;
- int i;
-
- if (instantiator_len < 1)
- {
- if (!no_error)
- signal_simple_error ("Vector length must be at least 1",
- instantiator);
- return 0;
- }
-
- meths = decode_image_instantiator_type (elt[0], no_error);
- if (!meths)
- /* Errors already reported */
- return 0;
-
- if (!(instantiator_len & 1))
- {
- if (!no_error)
- signal_simple_error ("Must have alternating keyword/value pairs",
- instantiator);
- return 0;
- }
-
- GCPRO1 (already_seen);
-
- for (i = 1; i < instantiator_len; i += 2)
- {
- Lisp_Object keyword = elt[i];
- Lisp_Object value = elt[i+1];
- int j;
-
- if (!SYMBOLP (keyword))
- {
- if (!no_error)
- CHECK_SYMBOL (keyword, 0);
- break;
- }
-
- if (!SYMBOL_IS_KEYWORD (keyword))
- {
- if (!no_error)
- signal_simple_error ("Symbol must begin with a colon",
- keyword);
- break;
- }
-
- for (j = 0; j < Dynarr_length (meths->keywords); j++)
- if (EQ (keyword, Dynarr_at (meths->keywords, j).keyword))
- break;
-
- if (j == Dynarr_length (meths->keywords))
- {
- if (!no_error)
- signal_simple_error ("Unrecognized keyword", keyword);
- break;
- }
-
- if (!Dynarr_at (meths->keywords, j).multiple_p)
- {
- if (!NILP (memq_no_quit (keyword, already_seen)))
- {
- if (!no_error)
- signal_simple_error
- ("Keyword may not appear more than once", keyword);
- break;
- }
- already_seen = Fcons (keyword, already_seen);
- }
-
- if (! (Dynarr_at (meths->keywords, j).validate) (value, no_error))
- {
- if (!no_error)
- /* No explanatory error provided */
- signal_simple_error_2 ("Invalid value for keyword", keyword,
- value);
- break;
- }
- }
-
- UNGCPRO;
-
- if (i < instantiator_len)
- return 0;
-
- if (!IITYPE_METH_OR_GIVEN (meths, validate, (instantiator, no_error), 1))
- {
- if (!no_error)
- signal_simple_error ("Something wrong with instantiator",
- instantiator);
- return 0;
- }
-
- return 1;
- }
- else if (!no_error)
- signal_simple_error ("Must be string or vector", instantiator);
-
- return 0;
- }
-
- static Lisp_Object
- normalize_image_instantiator (Lisp_Object instantiator, Lisp_Object devtype,
- int no_error)
- {
- if (STRINGP (instantiator))
- {
- instantiator =
- process_image_string_instantiator (instantiator, devtype, 1);
- if (NILP (instantiator))
- return Qnil;
- }
-
- assert (VECTORP (instantiator));
- /* We have to always store the actual pixmap data and not the
- filename even though this is a potential memory pig. We have to
- do this because it is quite possible that we will need to
- instantiate a new instance of the pixmap and the file will no
- longer exist (e.g. w3 pixmaps are almost always from temporary
- files). */
- instantiator =
- IITYPE_METH_OR_GIVEN
- (decode_image_instantiator_type
- (vector_data (XVECTOR (instantiator))[0], 1),
- normalize, (instantiator, devtype, no_error), instantiator);
-
- return instantiator;
- }
-
- static Lisp_Object
- instantiate_image_instantiator (Lisp_Object device, Lisp_Object instantiator,
- int dest_mask, int no_error)
- {
- Lisp_Object ii;
- int retval = 0;
- struct gcpro gcpro1;
-
- ii = allocate_image_instance (device);
-
- GCPRO1 (ii);
- retval = IITYPE_METH_OR_GIVEN
- (decode_image_instantiator_type
- (vector_data (XVECTOR (instantiator))[0], 1),
- instantiate, (ii, instantiator, dest_mask, no_error), 0);
- UNGCPRO;
-
- if (!retval)
- return Qnil;
-
- return ii;
- }
-
-
- /****************************************************************************
- * nothing *
- ****************************************************************************/
-
- static int
- nothing_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
- int dest_mask, int no_error)
- {
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-
- if (dest_mask & IMAGE_NOTHING_MASK)
- {
- IMAGE_INSTANCE_TYPE (ii) = IMAGE_NOTHING;
- return 1;
- }
- else
- {
- if (!no_error)
- signal_simple_error ("No compatible image-instance types given",
- instantiator);
- return 0;
- }
- }
-
-
- /****************************************************************************
- * formatted-string *
- ****************************************************************************/
-
- static int
- string_validate (Lisp_Object instantiator, int no_error)
- {
- return data_must_be_present (instantiator, no_error);
- }
-
- static int
- string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
- int dest_mask, int no_error)
- {
- Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-
- assert (!NILP (data));
- if (dest_mask & IMAGE_TEXT_MASK)
- {
- IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT;
- IMAGE_INSTANCE_TEXT_STRING (ii) = data;
- return 1;
- }
- else
- {
- if (!no_error)
- signal_simple_error ("No compatible image-instance types given",
- instantiator);
- return 0;
- }
- }
-
-
- /****************************************************************************
- * string *
- ****************************************************************************/
-
- static int
- formatted_string_validate (Lisp_Object instantiator, int no_error)
- {
- return data_must_be_present (instantiator, no_error);
- }
-
- static int
- formatted_string_instantiate (Lisp_Object image_instance,
- Lisp_Object instantiator,
- int dest_mask, int no_error)
- {
- Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-
- assert (!NILP (data));
- /* #### implement this */
- warn_when_safe (Qunimplemented, Qnotice,
- "`formatted-string' not yet implemented; assuming `string'");
- if (dest_mask & IMAGE_TEXT_MASK)
- {
- IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT;
- IMAGE_INSTANCE_TEXT_STRING (ii) = data;
- return 1;
- }
- else
- {
- if (!no_error)
- signal_simple_error ("No compatible image-instance types given",
- instantiator);
- return 0;
- }
- }
-
-
- /****************************************************************************
- * Image-Instance Object *
- ****************************************************************************/
-
- Lisp_Object Qimage_instancep;
- static Lisp_Object mark_image_instance (Lisp_Object, void (*) (Lisp_Object));
- static void print_image_instance (Lisp_Object, Lisp_Object, int);
- static void finalize_image_instance (void *, int);
- static int image_instance_equal (Lisp_Object o1, Lisp_Object o2, int depth);
- static unsigned long image_instance_hash (Lisp_Object obj, int depth);
- DEFINE_LRECORD_IMPLEMENTATION ("image-instance", image_instance,
- mark_image_instance, print_image_instance,
- finalize_image_instance, image_instance_equal,
- image_instance_hash,
- struct Lisp_Image_Instance);
- static Lisp_Object
- mark_image_instance (Lisp_Object obj, void (*markobj) (Lisp_Object))
- {
- struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
-
- (markobj) (i->name);
- switch (IMAGE_INSTANCE_TYPE (i))
- {
- case IMAGE_TEXT:
- (markobj) (IMAGE_INSTANCE_TEXT_STRING (i));
- break;
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- (markobj) (IMAGE_INSTANCE_PIXMAP_FILENAME (i));
- (markobj) (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i));
- (markobj) (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i));
- (markobj) (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i));
- break;
- case IMAGE_SUBWINDOW:
- /* #### implement me */
- break;
- default:
- break;
- }
-
- MAYBE_DEVMETH (XDEVICE (i->device), mark_image_instance, (i, markobj));
-
- return (i->device);
- }
-
- static void
- print_image_instance (Lisp_Object obj, Lisp_Object printcharfun,
- int escapeflag)
- {
- char buf[100];
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (obj);
-
- if (print_readably)
- error ("printing unreadable object #<image-instance 0x%x>",
- ii->header.uid);
- write_c_string ("#<image-instance (", printcharfun);
- print_internal (Fimage_instance_type (obj), printcharfun, 0);
- write_c_string (") ", printcharfun);
- if (!NILP (ii->name))
- {
- print_internal (ii->name, printcharfun, 1);
- write_c_string (" ", printcharfun);
- }
- write_c_string ("on ", printcharfun);
- print_internal (ii->device, printcharfun, 0);
- write_c_string (" ", printcharfun);
- switch (IMAGE_INSTANCE_TYPE (ii))
- {
- case IMAGE_NOTHING:
- break;
-
- case IMAGE_TEXT:
- print_internal (IMAGE_INSTANCE_TEXT_STRING (ii), printcharfun, 1);
- break;
-
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- if (STRINGP (IMAGE_INSTANCE_PIXMAP_FILENAME (ii)))
- {
- char *s;
- Lisp_Object filename = IMAGE_INSTANCE_PIXMAP_FILENAME (ii);
- s = strrchr ((char *) string_data (XSTRING (filename)), '/');
- if (s)
- print_internal (build_string (s + 1), printcharfun, 1);
- else
- print_internal (filename, printcharfun, 1);
- }
- if (IMAGE_INSTANCE_PIXMAP_DEPTH (ii) > 1)
- sprintf (buf, " %dx%dx%d", IMAGE_INSTANCE_PIXMAP_WIDTH (ii),
- IMAGE_INSTANCE_PIXMAP_HEIGHT (ii),
- IMAGE_INSTANCE_PIXMAP_DEPTH (ii));
- else
- sprintf (buf, " %dx%d", IMAGE_INSTANCE_PIXMAP_WIDTH (ii),
- IMAGE_INSTANCE_PIXMAP_HEIGHT (ii));
- write_c_string (buf, printcharfun);
- if (!NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ||
- !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)))
- {
- write_c_string (" @", printcharfun);
- if (!NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)))
- {
- sprintf (buf, "%d", XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)));
- write_c_string (buf, printcharfun);
- }
- else
- write_c_string ("??", printcharfun);
- write_c_string (",", printcharfun);
- if (!NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)))
- {
- sprintf (buf, "%d", XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)));
- write_c_string (buf, printcharfun);
- }
- else
- write_c_string ("??", printcharfun);
- }
- break;
-
- case IMAGE_SUBWINDOW:
- /* #### implement me */
- break;
-
- default:
- abort ();
- }
-
- MAYBE_DEVMETH (XDEVICE (ii->device), print_image_instance,
- (ii, printcharfun, escapeflag));
- sprintf (buf, " 0x%x>", ii->header.uid);
- write_c_string (buf, printcharfun);
- }
-
- static void
- finalize_image_instance (void *header, int for_disksave)
- {
- struct Lisp_Image_Instance *i = (struct Lisp_Image_Instance *) header;
-
- if (for_disksave) finalose (i);
-
- MAYBE_DEVMETH (XDEVICE (i->device), finalize_image_instance, (i));
- }
-
- static int
- image_instance_equal (Lisp_Object o1, Lisp_Object o2, int depth)
- {
- struct Lisp_Image_Instance *i1 = XIMAGE_INSTANCE (o1);
- struct Lisp_Image_Instance *i2 = XIMAGE_INSTANCE (o2);
- struct device *d1 = XDEVICE (i1->device);
- struct device *d2 = XDEVICE (i2->device);
-
- if (d1 != d2)
- return 0;
- if (IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2))
- return 0;
- if (!internal_equal (IMAGE_INSTANCE_NAME (i1), IMAGE_INSTANCE_NAME (i2),
- depth + 1))
- return 0;
-
- switch (IMAGE_INSTANCE_TYPE (i1))
- {
- case IMAGE_NOTHING:
- break;
-
- case IMAGE_TEXT:
- if (!internal_equal (IMAGE_INSTANCE_TEXT_STRING (i1),
- IMAGE_INSTANCE_TEXT_STRING (i2),
- depth + 1))
- return 0;
- break;
-
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- if (!(IMAGE_INSTANCE_PIXMAP_WIDTH (i1) ==
- IMAGE_INSTANCE_PIXMAP_WIDTH (i2) &&
- IMAGE_INSTANCE_PIXMAP_HEIGHT (i1) ==
- IMAGE_INSTANCE_PIXMAP_HEIGHT (i2) &&
- IMAGE_INSTANCE_PIXMAP_DEPTH (i1) ==
- IMAGE_INSTANCE_PIXMAP_DEPTH (i2) &&
- EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i1),
- IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i2)) &&
- EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i1),
- IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i2)) &&
- internal_equal (IMAGE_INSTANCE_PIXMAP_FILENAME (i1),
- IMAGE_INSTANCE_PIXMAP_FILENAME (i2),
- depth + 1) &&
- internal_equal (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i1),
- IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i2),
- depth + 1)))
- return 0;
- break;
-
- case IMAGE_SUBWINDOW:
- /* #### implement me */
- break;
-
- default:
- abort ();
- }
-
- return DEVMETH_OR_GIVEN (d1, image_instance_equal, (i1, i2, depth), 1);
- }
-
- static unsigned long
- image_instance_hash (Lisp_Object obj, int depth)
- {
- struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
- struct device *d = XDEVICE (i->device);
- unsigned long hash = (unsigned long) d;
-
- switch (IMAGE_INSTANCE_TYPE (i))
- {
- case IMAGE_NOTHING:
- break;
-
- case IMAGE_TEXT:
- hash = HASH2 (hash, internal_hash (IMAGE_INSTANCE_TEXT_STRING (i),
- depth + 1));
- break;
-
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- hash = HASH5 (hash, IMAGE_INSTANCE_PIXMAP_WIDTH (i),
- IMAGE_INSTANCE_PIXMAP_HEIGHT (i),
- IMAGE_INSTANCE_PIXMAP_DEPTH (i),
- internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i),
- depth + 1));
- break;
-
- case IMAGE_SUBWINDOW:
- /* #### implement me */
- break;
-
- default:
- abort ();
- }
-
- return HASH2 (hash, DEVMETH_OR_GIVEN (d, image_instance_hash, (i, depth),
- 0));
- }
-
- static Lisp_Object
- allocate_image_instance (Lisp_Object device)
- {
- struct Lisp_Image_Instance *lp =
- alloc_lcrecord (sizeof (struct Lisp_Image_Instance),
- lrecord_image_instance);
- Lisp_Object val = Qnil;
-
- zero_lcrecord (lp);
- lp->device = device;
- lp->type = IMAGE_NOTHING;
- lp->name = Qnil;
- XSETIMAGE_INSTANCE (val, lp);
- return val;
- }
-
- static enum image_instance_type
- decode_image_instance_type (Lisp_Object type, int no_error)
- {
- if (!no_error)
- CHECK_SYMBOL (type, 0);
-
- if (EQ (type, Qnothing))
- return IMAGE_NOTHING;
- if (EQ (type, Qtext))
- return IMAGE_TEXT;
- if (EQ (type, Qmono_pixmap))
- return IMAGE_MONO_PIXMAP;
- if (EQ (type, Qcolor_pixmap))
- return IMAGE_COLOR_PIXMAP;
- if (EQ (type, Qcursor))
- return IMAGE_CURSOR;
- if (EQ (type, Qsubwindow))
- return IMAGE_SUBWINDOW;
-
- if (!no_error)
- signal_simple_error ("Invalid image-instance type", type);
- return IMAGE_UNKNOWN;
- }
-
- static int
- image_instance_type_to_mask (enum image_instance_type type)
- {
- /* This depends on the fact that enums are assigned consecutive
- integers starting at 0. (Remember that IMAGE_UNKNOWN is the
- first enum.) I'm fairly sure this behavior in ANSI-mandated,
- so there should be no portability problems here. */
- return (1 << ((int) (type) - 1));
- }
-
- static int
- decode_image_instance_type_list (Lisp_Object list, int no_error)
- {
- Lisp_Object rest;
- int mask = 0;
-
- if (NILP (list))
- return ~0;
-
- if (!CONSP (list))
- {
- enum image_instance_type type = decode_image_instance_type (list,
- no_error);
- if (type == IMAGE_UNKNOWN)
- return 0;
- return image_instance_type_to_mask (type);
- }
-
- EXTERNAL_LIST_LOOP (rest, list)
- {
- enum image_instance_type type = decode_image_instance_type (XCAR (rest),
- no_error);
- if (type == IMAGE_UNKNOWN)
- return 0;
- mask |= image_instance_type_to_mask (type);
- }
-
- return mask;
- }
-
- static int
- valid_image_instance_type_p (Lisp_Object type)
- {
- if (!NILP (memq_no_quit (type, Vimage_instance_type_list)))
- return 1;
- return 0;
- }
-
- DEFUN ("valid-image-instance-type-p", Fvalid_image_instance_type_p,
- Svalid_image_instance_type_p, 1, 1, 0,
- "Given an IMAGE-INSTANCE-TYPE, return non-nil if it is valid.\n\
- Valid types are some subset of 'nothing, 'text, 'mono-pixmap, 'color-pixmap,\n\
- 'cursor, and 'subwindow, depending on how XEmacs was compiled.")
- (image_instance_type)
- Lisp_Object image_instance_type;
- {
- if (valid_image_instance_type_p (image_instance_type))
- return Qt;
- else
- return Qnil;
- }
-
- DEFUN ("image-instance-type-list", Fimage_instance_type_list,
- Simage_instance_type_list,
- 0, 0, 0,
- "Return a list of valid image-instance types.")
- ()
- {
- return Fcopy_sequence (Vimage_instance_type_list);
- }
-
- DEFUN ("make-image-instance", Fmake_image_instance, Smake_image_instance,
- 1, 4, 0,
- "Create a new `image-instance' object.\n\
- \n\
- Image-instance objects encapsulate the way a particular image (pixmap,\n\
- etc.) is displayed on a particular device. In most circumstances, you\n\
- do not need to directly create image instances; use a glyph or an image-\n\
- specifier instead. (Most functions and data structures that want an image\n\
- are designed to take either a glyph or an image-specifier.)\n\
- \n\
- DATA is an image instantiator; see `image-specifier-p' for a description\n\
- of the allowed values.")
- (data, device, dest_types, no_error)
- Lisp_Object data, device, dest_types, no_error;
- {
- Lisp_Object ii;
- struct gcpro gcpro1;
- int dest_mask;
-
- XSETDEVICE (device, get_device (device));
-
- if (!validate_image_instantiator (data, !NILP (no_error)))
- return Qnil;
-
- dest_mask = decode_image_instance_type_list (dest_types, !NILP (no_error));
- if (!dest_mask)
- return Qnil;
-
- data = normalize_image_instantiator (data, Fdevice_type (device),
- !NILP (no_error));
- if (NILP (data))
- return Qnil;
-
- GCPRO1 (data);
- ii = instantiate_image_instantiator (device, data, dest_mask,
- !NILP (no_error));
- RETURN_UNGCPRO (ii);
- }
-
- DEFUN ("image-instance-p", Fimage_instance_p, Simage_instance_p, 1, 1, 0,
- "Return non-nil if OBJECT is an image instance.")
- (object)
- Lisp_Object object;
- {
- return (IMAGE_INSTANCEP (object) ? Qt : Qnil);
- }
-
- DEFUN ("image-instance-type", Fimage_instance_type, Simage_instance_type,
- 1, 1, 0,
- "Return the type of the given image instance.\n\
- The return value will be one of 'nothing, 'text, 'mono-pixmap,\n\
- 'color-pixmap, 'cursor, or 'subwindow.")
- (image_instance)
- Lisp_Object image_instance;
- {
- CHECK_IMAGE_INSTANCE (image_instance, 0);
- switch (XIMAGE_INSTANCE_TYPE (image_instance))
- {
- case IMAGE_NOTHING:
- return Qnothing;
- case IMAGE_TEXT:
- return Qtext;
- case IMAGE_MONO_PIXMAP:
- return Qmono_pixmap;
- case IMAGE_COLOR_PIXMAP:
- return Qcolor_pixmap;
- case IMAGE_CURSOR:
- return Qcursor;
- case IMAGE_SUBWINDOW:
- return Qsubwindow;
- default:
- abort ();
- }
-
- return Qnil; /* not reached */
- }
-
- DEFUN ("image-instance-name", Fimage_instance_name,
- Simage_instance_name, 1, 1, 0,
- "Return the name of the given image instance.")
- (image_instance)
- Lisp_Object image_instance;
- {
- CHECK_IMAGE_INSTANCE (image_instance, 0);
- return (XIMAGE_INSTANCE_NAME (image_instance));
- }
-
- DEFUN ("image-instance-string", Fimage_instance_string,
- Simage_instance_string, 1, 1, 0,
- "Return the string of the given image instance.")
- (image_instance)
- Lisp_Object image_instance;
- {
- CHECK_IMAGE_INSTANCE (image_instance, 0);
- return (XIMAGE_INSTANCE_TEXT_STRING (image_instance));
- }
-
- DEFUN ("image-instance-file-name", Fimage_instance_file_name,
- Simage_instance_file_name, 1, 1, 0,
- "Return the file name from which IMAGE-INSTANCE was read, if known.")
- (image_instance)
- Lisp_Object image_instance;
- {
- CHECK_IMAGE_INSTANCE (image_instance, 0);
-
- switch (XIMAGE_INSTANCE_TYPE (image_instance))
- {
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- return XIMAGE_INSTANCE_PIXMAP_FILENAME (image_instance);
-
- default:
- return Qnil;
- }
- }
-
- DEFUN ("image-instance-mask-file-name", Fimage_instance_mask_file_name,
- Simage_instance_mask_file_name, 1, 1, 0,
- "Return the file name from which IMAGE-INSTANCE's mask was read, if known.")
- (image_instance)
- Lisp_Object image_instance;
- {
- CHECK_IMAGE_INSTANCE (image_instance, 0);
-
- switch (XIMAGE_INSTANCE_TYPE (image_instance))
- {
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- return XIMAGE_INSTANCE_PIXMAP_MASK_FILENAME (image_instance);
-
- default:
- return Qnil;
- }
- }
-
- DEFUN ("image-instance-depth", Fimage_instance_depth,
- Simage_instance_depth, 1, 1, 0,
- "Return the depth of the image instance.\n\
- This is 0 for a bitmap, or a positive integer for a pixmap.")
- (image_instance)
- Lisp_Object image_instance;
- {
- CHECK_IMAGE_INSTANCE (image_instance, 0);
-
- switch (XIMAGE_INSTANCE_TYPE (image_instance))
- {
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- return (make_number (XIMAGE_INSTANCE_PIXMAP_DEPTH (image_instance)));
-
- default:
- return Qnil;
- }
- }
-
- DEFUN ("image-instance-height", Fimage_instance_height,
- Simage_instance_height, 1, 1, 0,
- "Return the height of the image instance, in pixels.")
- (image_instance)
- Lisp_Object image_instance;
- {
- CHECK_IMAGE_INSTANCE (image_instance, 0);
-
- switch (XIMAGE_INSTANCE_TYPE (image_instance))
- {
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- return (make_number (XIMAGE_INSTANCE_PIXMAP_HEIGHT (image_instance)));
-
- default:
- return Qnil;
- }
- }
-
- DEFUN ("image-instance-width", Fimage_instance_width,
- Simage_instance_width, 1, 1, 0,
- "Return the width of the image instance, in pixels.")
- (image_instance)
- Lisp_Object image_instance;
- {
- CHECK_IMAGE_INSTANCE (image_instance, 0);
-
- switch (XIMAGE_INSTANCE_TYPE (image_instance))
- {
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- return (make_number (XIMAGE_INSTANCE_PIXMAP_WIDTH (image_instance)));
-
- default:
- return Qnil;
- }
- }
-
- DEFUN ("set-image-instance-hotspot", Fset_image_instance_hotspot,
- Sset_image_instance_hotspot,
- 3, 3, 0,
- "Set the image instance's hotspot.\n\
- This is a point relative to the origin of the pixmap. When a pixmap is\n\
- used as a cursor or similar pointing indicator, the hotspot is the point\n\
- on the pixmap that sits over the location that the pointer points to.\n\
- This is, for example, the tip of the arrow or the center of the crosshairs.")
- (image_instance, x, y)
- Lisp_Object image_instance, x, y;
- {
- CHECK_IMAGE_INSTANCE (image_instance, 0);
- if (!NILP (x))
- CHECK_INT (x, 0);
- if (!NILP (y))
- CHECK_INT (y, 0);
-
- switch (XIMAGE_INSTANCE_TYPE (image_instance))
- {
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- {
- struct Lisp_Image_Instance *p;
-
- p = XIMAGE_INSTANCE (image_instance);
- IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (p) = x;
- IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (p) = y;
- break;
- }
-
- default:
- signal_simple_error ("Cannot set hotspot of non-pixmap image-instance",
- image_instance);
- }
-
- return Qnil;
- }
-
- DEFUN ("image-instance-hotspot-x", Fimage_instance_hotspot_x,
- Simage_instance_hotspot_x, 1, 1, 0,
- "Return the X coordinate of the image instance's hotspot.\n\
- See `set-image-instance-hotspot'.")
- (image_instance)
- Lisp_Object image_instance;
- {
- CHECK_IMAGE_INSTANCE (image_instance, 0);
-
- switch (XIMAGE_INSTANCE_TYPE (image_instance))
- {
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- return XIMAGE_INSTANCE_PIXMAP_HOTSPOT_X (image_instance);
-
- default:
- return Qnil;
- }
- }
-
- DEFUN ("image-instance-hotspot-y", Fimage_instance_hotspot_y,
- Simage_instance_hotspot_y, 1, 1, 0,
- "Return the Y coordinate of the image instance's hotspot.\n\
- See `set-image-instance-hotspot'.")
- (image_instance)
- Lisp_Object image_instance;
- {
- CHECK_IMAGE_INSTANCE (image_instance, 0);
-
- switch (XIMAGE_INSTANCE_TYPE (image_instance))
- {
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- return XIMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (image_instance);
-
- default:
- return Qnil;
- }
- }
-
-
- /****************************************************************************
- * Image Specifier Object *
- ****************************************************************************/
-
- DEFINE_SPECIFIER_TYPE (image);
-
- static void
- image_create (Lisp_Object obj)
- {
- struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
-
- IMAGE_SPECIFIER_ALLOWED (image) = ~0; /* all are allowed */
- IMAGE_SPECIFIER_FACE (image) = Qnil;
- IMAGE_SPECIFIER_FACE_PROPERTY (image) = Qnil;
- }
-
- static void
- image_mark (Lisp_Object obj, void (*markobj) (Lisp_Object))
- {
- struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
-
- ((markobj) (IMAGE_SPECIFIER_FACE (image)));
- ((markobj) (IMAGE_SPECIFIER_FACE_PROPERTY (image)));
- }
-
- /* Given a specification for an image, return an instance of
- the image which matches the given instantiator and which can be
- displayed in the given domain. */
-
- static Lisp_Object
- image_instantiate_1 (Lisp_Object device, Lisp_Object instantiator,
- int dest_mask, int no_quit)
- {
- return instantiate_image_instantiator (device, instantiator,
- dest_mask, 1);
- }
-
- static Lisp_Object
- image_instantiate (Lisp_Object specifier, Lisp_Object domain,
- Lisp_Object instantiator, int no_quit)
- {
- Lisp_Object device = DFW_DEVICE (domain);
- struct device *d = XDEVICE (device);
- int dest_mask = XIMAGE_SPECIFIER_ALLOWED (specifier);
-
- if (IMAGE_INSTANCEP (instantiator))
- {
- /* make sure that the image instance's device and type are
- matching. */
-
- if (EQ (device, XIMAGE_INSTANCE_DEVICE (instantiator)))
- {
- int mask =
- image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instantiator));
- if (mask & dest_mask)
- return instantiator;
- else
- return Qunbound;
- }
- else
- return Qunbound;
- }
- else
- {
- Lisp_Object instance;
- Lisp_Object subtable;
-
- /* First look in the hash table. */
- subtable = Fgethash (make_number (dest_mask), d->image_instance_cache,
- Qunbound);
- if (UNBOUNDP (subtable))
- {
- /* For the image instance cache, we do comparisons with EQ rather
- than with EQUAL, as we do for color and font names.
- The reasons are:
-
- 1) pixmap data can be very long, and thus the hashing and
- comparing will take awhile.
- 2) It's not so likely that we'll run into things that are EQUAL
- but not EQ (that can happen a lot with faces, because their
- specifiers are copied around); but pixmaps tend not to be
- in faces.
- 3) pixmap data could be in vector form as well as in string
- form, and so writing a hash function would be trickier.
- */
-
- subtable = make_lisp_hashtable (20, 0, 0, HASHTABLE_KEY_WEAK);
- Fputhash (make_number (dest_mask), subtable,
- d->image_instance_cache);
- instance = Qunbound;
- }
- else
- instance = Fgethash (instantiator, subtable, Qunbound);
-
- if (UNBOUNDP (instance))
- {
- /* make sure we cache the failures, too. */
- instance = image_instantiate_1 (device, instantiator, dest_mask,
- no_quit);
- Fputhash (instantiator, instance, subtable);
- }
-
- return (NILP (instance) ? Qunbound : instance);
- }
- }
-
- /* Validate an image instantiator. */
-
- static int
- image_validate (Lisp_Object instantiator, int no_error)
- {
- if (IMAGE_INSTANCEP (instantiator))
- return 1;
- return validate_image_instantiator (instantiator, no_error);
- }
-
- static void
- image_after_change (Lisp_Object specifier, Lisp_Object locale)
- {
- Lisp_Object face = IMAGE_SPECIFIER_FACE (XIMAGE_SPECIFIER (specifier));
- Lisp_Object property =
- IMAGE_SPECIFIER_FACE_PROPERTY (XIMAGE_SPECIFIER (specifier));
- if (!NILP (face))
- face_property_was_changed (face, property, locale);
- }
-
- void
- set_image_attached_to (Lisp_Object obj, Lisp_Object face, Lisp_Object property)
- {
- struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
-
- IMAGE_SPECIFIER_FACE (image) = face;
- IMAGE_SPECIFIER_FACE_PROPERTY (image) = property;
- }
-
- static Lisp_Object
- image_going_to_add (Lisp_Object specifier, Lisp_Object locale,
- Lisp_Object tag_set, Lisp_Object instantiator)
- {
- Lisp_Object possible_device_types = Qnil;
- Lisp_Object rest;
- Lisp_Object retlist = Qnil;
- struct gcpro gcpro1, gcpro2;
-
- LIST_LOOP (rest, Vdevice_type_list)
- {
- Lisp_Object devtype = XCAR (rest);
- if (!NILP (memq_no_quit (devtype, tag_set)))
- possible_device_types = Fcons (devtype, possible_device_types);
- }
-
- if (XINT (Flength (possible_device_types)) > 1)
- /* two conflicting device types specified */
- return Qnil;
-
- if (NILP (possible_device_types))
- possible_device_types = Vdevice_type_list;
-
- GCPRO2 (retlist, possible_device_types);
-
- LIST_LOOP (rest, possible_device_types)
- {
- Lisp_Object newinst;
- Lisp_Object devtype = XCAR (rest);
-
- newinst = normalize_image_instantiator (instantiator, devtype, 1);
- if (!NILP (newinst))
- {
- Lisp_Object newtag;
- if (NILP (memq_no_quit (devtype, tag_set)))
- newtag = Fcons (devtype, tag_set);
- else
- newtag = tag_set;
- retlist = Fcons (Fcons (newtag, newinst), retlist);
- }
- }
-
- UNGCPRO;
-
- return retlist;
- }
-
- DEFUN ("image-specifier-p", Fimage_specifier_p, Simage_specifier_p, 1, 1, 0,
- "Return non-nil if OBJECT is an image specifier.\n\
- \n\
- An image specifier is used for images (pixmaps and the like). It is used\n\
- to describe the actual image in a glyph. It is instanced as an image-\n\
- instance.\n\
- \n\
- An image instantiator should be a string or a vector of the form\n\
- \n\
- [TYPE :KEYWORD VALUE ...]\n\
- \n\
- i.e. a type symbol followed by zero or more alternating keyword-value\n\
- pairs. TYPE should be one of\n\
- \n\
- 'nothing\n\
- (Don't display anything; no keywords are valid for this.)\n\
- 'string\n\
- (Display this image as a text string.)\n\
- 'formatted-string\n\
- (Display this image as a text string, with replaceable fields;\n\
- #### not implemented in 19.13.)\n\
- 'xbm\n\
- (An X bitmap; only if X support was compiled into this XEmacs.)\n\
- 'xpm\n\
- (An XPM pixmap; only if XPM support was compiled into this XEmacs.)\n\
- 'xface\n\
- (An X-Face bitmap, used to encode people's faces in e-mail messages;\n\
- only if X-Face support was compiled into this XEmacs.)\n\
- 'gif\n\
- (A GIF87 or GIF89 image; only if GIF support was compiled into this\n\
- XEmacs.)\n\
- 'jpeg\n\
- (A JPEG image; only if JPEG support was compiled into this XEmacs.)\n\
- 'png\n\
- (A PNG/GIF24 image; only if PNG support was compiled into this XEmacs.)\n\
- 'autodetect\n\
- (XEmacs tries to guess what format the data is in. If X support\n\
- exists, the data string will be checked to see if it names a filename.\n\
- If so, and this filename contains XBM or XPM data, the appropriate\n\
- sort of pixmap will be created. Otherwise, the image will be displayed\n\
- as a string. If no X support exists, the image will always be displayed\n\
- as a string.)\n\
- \n\
- The valid keywords are:\n\
- \n\
- :data\n\
- (Inline data. For most formats above, this should be a string. For\n\
- XBM images, this should be a cons of three elements: width, height, and\n\
- a string of bit data.)\n\
- :file\n\
- (Data is contained in a file. The value is the name of this file.\n\
- If both :data and :file are specified, the image is created from\n\
- what is specified in :data and the string in :file becomes the\n\
- value of the `image-instance-file-name' function when applied to\n\
- the resulting image-instance.)\n\
- :mask-data\n\
- (Only for XBM images. This specifies a mask to be used with the\n\
- bitmap. The format is a cons of width, height, and bits, like for\n\
- :data.)\n\
- :mask-file\n\
- (Only for XBM images. This specifies a file containing the mask data.)\n\
- :color-symbols\n\
- (Only for XPM images. This specifies an alist that maps strings\n\
- that specify symbolic color names to the actual color to be used\n\
- for that symbolic color (in the form of a string or a color-specifier\n\
- object). If this is not specified, the contents of `xpm-color-symbols'\n\
- are used to generate the alist.)\n\
- \n\
- If instead of a vector, the instantiator is a string, it will be looked\n\
- up according to the specs in the `device-type-image-conversion-list' (q.v.)\n\
- for the device type of the domain over which the image is being\n\
- instantiated.\n\
- \n\
- If the instantiator is a string, it will be read in at the time that the\n\
- instantiator is added to the image, and the instantiator will be converted\n\
- into one of the [FILENAME ...] forms. This implies that the file must exist\n\
- when the instantiator is added to the image, but does not need to exist at\n\
- any other time (e.g. it may be a temporary file).")
- (object)
- Lisp_Object object;
- {
- return (IMAGE_SPECIFIERP (object) ? Qt : Qnil);
- }
-
-
- /****************************************************************************
- * Glyph Object *
- ****************************************************************************/
-
- static Lisp_Object mark_glyph (Lisp_Object, void (*) (Lisp_Object));
- static void print_glyph (Lisp_Object, Lisp_Object, int);
- static int glyph_equal (Lisp_Object, Lisp_Object, int depth);
- static unsigned long glyph_hash (Lisp_Object obj, int depth);
- static int glyph_getprop (Lisp_Object obj, Lisp_Object prop,
- Lisp_Object *value_out);
- static int glyph_putprop (Lisp_Object obj, Lisp_Object prop,
- Lisp_Object value);
- static int glyph_remprop (Lisp_Object obj, Lisp_Object prop);
- static Lisp_Object glyph_props (Lisp_Object obj);
- DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("glyph", glyph,
- mark_glyph, print_glyph, 0,
- glyph_equal, glyph_hash,
- glyph_getprop, glyph_putprop,
- glyph_remprop, glyph_props,
- struct Lisp_Glyph);
-
- static Lisp_Object
- mark_glyph (Lisp_Object obj, void (*markobj) (Lisp_Object))
- {
- struct Lisp_Glyph *glyph = XGLYPH (obj);
-
- ((markobj) (glyph->image));
- ((markobj) (glyph->contrib_p));
- ((markobj) (glyph->baseline));
- ((markobj) (glyph->face));
-
- return (glyph->plist);
- }
-
- static void
- print_glyph (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
- {
- struct Lisp_Glyph *glyph = XGLYPH (obj);
- char buf[20];
-
- if (print_readably)
- error ("printing unreadable object #<glyph 0x%x>", glyph->header.uid);
-
- write_c_string ("#<glyph (", printcharfun);
- print_internal (Fglyph_type (obj), printcharfun, 0);
- write_c_string (") ", printcharfun);
- print_internal (glyph->image, printcharfun, 1);
- sprintf (buf, "0x%x>", glyph->header.uid);
- write_c_string (buf, printcharfun);
- }
-
- /* Glyphs are equal if all of their display attributes are equal. We
- don't compare names or doc-strings, because that would make equal
- be eq.
-
- This isn't concerned with "unspecified" attributes, that's what
- #'glyph-differs-from-default-p is for. */
- static int
- glyph_equal (Lisp_Object o1, Lisp_Object o2, int depth)
- {
- struct Lisp_Glyph *g1 = XGLYPH (o1);
- struct Lisp_Glyph *g2 = XGLYPH (o2);
-
- depth++;
-
- if (!internal_equal (g1->image, g2->image, depth) ||
- !internal_equal (g1->contrib_p, g2->contrib_p, depth) ||
- !internal_equal (g1->baseline, g2->baseline, depth) ||
- !internal_equal (g1->face, g2->face, depth) ||
- plists_differ (g1->plist, g2->plist, depth + 1))
- return 0;
-
- return 1;
- }
-
- static unsigned long
- glyph_hash (Lisp_Object obj, int depth)
- {
- struct Lisp_Glyph *g = XGLYPH (obj);
-
- depth++;
-
- /* No need to hash all of the elements; that would take too long.
- Just hash the most common ones. */
- return HASH2 (internal_hash (g->image, depth),
- internal_hash (g->face, depth));
- }
-
- static int
- glyph_getprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object *value_out)
- {
- struct Lisp_Glyph *g = XGLYPH (obj);
-
- #define FROB(propprop) \
- do { \
- if (EQ (prop, Q##propprop)) \
- { \
- *value_out = g->propprop; \
- return 1; \
- } \
- } while (0)
-
- FROB (image);
- FROB (contrib_p);
- FROB (baseline);
- FROB (face);
-
- #undef FROB
-
- return internal_getf (g->plist, prop, value_out);
- }
-
- static int
- glyph_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value)
- {
- struct Lisp_Glyph *g = XGLYPH (obj);
-
- #define FROB(propprop) \
- do { \
- if (EQ (prop, Q##propprop)) \
- return 0; \
- } while (0)
-
- FROB (image);
- FROB (contrib_p);
- FROB (baseline);
-
- #undef FROB
-
- if (EQ (prop, Qface))
- {
- value = Fget_face (value);
- g->face = value;
- return 1;
- }
-
- internal_putf (&g->plist, prop, value);
- return 1;
- }
-
- static int
- glyph_remprop (Lisp_Object obj, Lisp_Object prop)
- {
- struct Lisp_Glyph *g = XGLYPH (obj);
-
- #define FROB(propprop) \
- do { \
- if (EQ (prop, Q##propprop)) \
- return -1; \
- } while (0)
-
- FROB (image);
- FROB (contrib_p);
- FROB (baseline);
-
- if (EQ (prop, Qface))
- {
- g->face = Qnil;
- return 1;
- }
-
- #undef FROB
- return internal_remprop (&g->plist, prop);
- }
-
- static Lisp_Object
- glyph_props (Lisp_Object obj)
- {
- struct Lisp_Glyph *g = XGLYPH (obj);
- Lisp_Object result = Qnil;
-
- #define FROB(propprop) \
- do { \
- result = Fcons (g->propprop, Fcons (Q##propprop, result)); \
- } while (0)
-
- /* backwards order; we reverse it below */
- FROB (face);
- FROB (baseline);
- FROB (contrib_p);
- FROB (image);
-
- #undef FROB
- return nconc2 (Fnreverse (result), Fcopy_sequence (g->plist));
- }
-
- static Lisp_Object
- make_glyph (enum glyph_type type)
- {
- Lisp_Object obj = Qnil;
- struct Lisp_Glyph *g =
- alloc_lcrecord (sizeof (struct Lisp_Glyph), lrecord_glyph);
-
- g->type = type;
- g->image = Fmake_specifier (Qimage);
- switch (g->type)
- {
- case GLYPH_BUFFER:
- XIMAGE_SPECIFIER_ALLOWED (g->image) =
- IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK | IMAGE_MONO_PIXMAP_MASK |
- IMAGE_COLOR_PIXMAP_MASK | IMAGE_SUBWINDOW_MASK;
- break;
- case GLYPH_CURSOR:
- XIMAGE_SPECIFIER_ALLOWED (g->image) = IMAGE_CURSOR_MASK;
- break;
- case GLYPH_ICON:
- XIMAGE_SPECIFIER_ALLOWED (g->image) = IMAGE_MONO_PIXMAP_MASK |
- IMAGE_COLOR_PIXMAP_MASK;
- break;
- default:
- abort ();
- }
-
- set_specifier_fallback (g->image, list1 (Fcons (Qnil, Vthe_nothing_vector)));
- g->contrib_p = Fmake_specifier (Qboolean);
- set_specifier_fallback (g->contrib_p, list1 (Fcons (Qnil, Qt)));
- /* #### should have a specifier for the following */
- g->baseline = Fmake_specifier (Qgeneric);
- set_specifier_fallback (g->baseline, list1 (Fcons (Qnil, Qnil)));
- g->face = Qnil;
- g->plist = Qnil;
-
- XSETGLYPH (obj, g);
- return obj;
- }
-
- static enum glyph_type
- decode_glyph_type (Lisp_Object type, int no_error)
- {
- if (NILP (type))
- return GLYPH_BUFFER;
-
- if (!no_error)
- CHECK_SYMBOL (type, 0);
-
- if (EQ (type, Qbuffer))
- return GLYPH_BUFFER;
- if (EQ (type, Qcursor))
- return GLYPH_CURSOR;
- if (EQ (type, Qicon))
- return GLYPH_ICON;
-
- if (!no_error)
- signal_simple_error ("Invalid glyph type", type);
- return GLYPH_UNKNOWN;
- }
-
- static int
- valid_glyph_type_p (Lisp_Object type)
- {
- if (!NILP (memq_no_quit (type, Vglyph_type_list)))
- return 1;
- return 0;
- }
-
- DEFUN ("valid-glyph-type-p", Fvalid_glyph_type_p,
- Svalid_glyph_type_p, 1, 1, 0,
- "Given an GLYPH-TYPE, return non-nil if it is valid.\n\
- Valid types are some subset of 'nothing, 'text, 'mono-pixmap, 'color-pixmap,\n\
- 'cursor, and 'subwindow, depending on how XEmacs was compiled.")
- (glyph_type)
- Lisp_Object glyph_type;
- {
- if (valid_glyph_type_p (glyph_type))
- return Qt;
- else
- return Qnil;
- }
-
- DEFUN ("glyph-type-list", Fglyph_type_list,
- Sglyph_type_list,
- 0, 0, 0,
- "Return a list of valid glyph types.")
- ()
- {
- return Fcopy_sequence (Vglyph_type_list);
- }
-
- DEFUN ("make-glyph-internal", Fmake_glyph_internal, Smake_glyph_internal,
- 0, 1, 0,
- "Create a new, uninitialized glyph.")
- (type)
- Lisp_Object type;
- {
- enum glyph_type typeval = decode_glyph_type (type, 0);
- return make_glyph (typeval);
- }
-
- DEFUN ("glyphp", Fglyphp, Sglyphp, 1, 1, 0,
- "Return non-nil if OBJECT is a glyph.\n\
- \n\
- A glyph is an object used for pixmaps and the like. It is used\n\
- in begin-glyphs and end-glyphs attached to extents, in marginal and textual\n\
- annotations, in overlay arrows (overlay-arrow-* variables), in toolbar\n\
- buttons, and the like. Its image is described using an image specifier --\n\
- see `image-specifier-p'.")
- (object)
- Lisp_Object object;
- {
- return GLYPHP (object) ? Qt : Qnil;
- }
-
- DEFUN ("glyph-type", Fglyph_type, Sglyph_type,
- 1, 1, 0,
- "Return the type of the given glyph.\n\
- The return value will be one of 'buffer, 'cursor, or 'icon.")
- (glyph)
- Lisp_Object glyph;
- {
- CHECK_GLYPH (glyph, 0);
- switch (XGLYPH_TYPE (glyph))
- {
- case GLYPH_BUFFER:
- return Qbuffer;
- case GLYPH_CURSOR:
- return Qcursor;
- case GLYPH_ICON:
- return Qicon;
- default:
- abort ();
- }
-
- return Qnil; /* not reached */
- }
-
- /*****************************************************************************
- glyph_width
-
- Return the width of the given GLYPH on the given WINDOW. If the
- instance is a string then the width is calculated using the font of
- the given FACE.
- ****************************************************************************/
- unsigned short
- glyph_width (Lisp_Object glyph, face_index findex, int framep,
- Lisp_Object window)
- {
- Lisp_Object instance;
- Lisp_Object frame = XWINDOW (window)->frame;
-
- /* #### We somehow need to distinguish between the user causing this
- error condition and a bug causing it. */
- if (!GLYPHP (glyph))
- return 0;
- else
- instance = glyph_image_instance (glyph, window, 1);
-
- switch (XIMAGE_INSTANCE_TYPE (instance))
- {
- case IMAGE_TEXT:
- {
- struct device *d = XDEVICE (XFRAME (frame)->device);
- struct Lisp_String *str =
- XSTRING (XIMAGE_INSTANCE_TEXT_STRING (instance));
- Lisp_Object font;
-
- /* #### more lossage. See add_glyph_rune(). */
- #ifdef MULE
- lose; /* !!#### */
- #else
- int i;
- int len = string_length (str);
- Emchar *bogobogo = (Emchar *) alloca (len * sizeof (Emchar));
- for (i = 0; i < len; i++)
- bogobogo[i] = (Emchar) string_byte (str, i);
-
- if (framep)
- font = FACE_FONT (Vdefault_face, frame);
- else
- font = FACE_CACHE_ELEMENT_FONT (XWINDOW (window), findex);
-
- return (DEVMETH (d, text_width,
- (XWINDOW (window), font, bogobogo, len)));
- #endif
- }
-
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- return XIMAGE_INSTANCE_PIXMAP_WIDTH (instance);
-
- case IMAGE_NOTHING:
- return 0;
-
- case IMAGE_SUBWINDOW:
- /* #### implement me */
- return 0;
-
- default:
- abort ();
- return 0;
- }
- }
-
- DEFUN ("glyph-width", Fglyph_width, Sglyph_width, 1, 2, 0,
- "Return the width of GLYPH on WINDOW.\n\
- This may not be exact as it does not take into account all of the context\n\
- that redisplay will.")
- (glyph, window)
- Lisp_Object glyph, window;
- {
- XSETWINDOW (window, decode_window (window));
- CHECK_GLYPH (glyph, 0);
-
- return (make_number (glyph_width (glyph, DEFAULT_INDEX, 0, window)));
- }
-
- #define RETURN_ASCENT 0
- #define RETURN_DESCENT 1
- #define RETURN_HEIGHT 2
-
- Lisp_Object
- glyph_image_instance (Lisp_Object glyph, Lisp_Object domain,
- int no_error_or_quit)
- {
- Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph));
-
- /* This can never return Qunbound. All glyphs have 'nothing as
- a fallback. */
- return specifier_instance (specifier, domain, no_error_or_quit, 0);
- }
-
- static unsigned short
- glyph_height_internal (Lisp_Object glyph, face_index findex, int framep,
- Lisp_Object window, int function)
- {
- Lisp_Object instance;
- Lisp_Object frame = XWINDOW (window)->frame;
-
- if (!GLYPHP (glyph))
- return 0;
- else
- instance = glyph_image_instance (glyph, window, 1);
-
- switch (XIMAGE_INSTANCE_TYPE (instance))
- {
- case IMAGE_TEXT:
- {
- struct device *d = XDEVICE (XFRAME (frame)->device);
- struct font_metric_info fm;
- Lisp_Object font;
-
- if (framep)
- font = FACE_FONT (Vdefault_face, frame);
- else
- font = FACE_CACHE_ELEMENT_FONT (XWINDOW (window), findex);
-
- DEVMETH (d, font_metric_info, (d, font, &fm));
-
- if (function == RETURN_ASCENT)
- return fm.ascent;
- else if (function == RETURN_DESCENT)
- return fm.descent;
- else if (function == RETURN_HEIGHT)
- return fm.ascent + fm.descent;
- else
- abort ();
- return 0;
- }
-
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- /* #### Ugh ugh ugh -- temporary crap */
- if (function == RETURN_ASCENT || function == RETURN_HEIGHT)
- return XIMAGE_INSTANCE_PIXMAP_HEIGHT (instance);
- else
- return 0;
-
- case IMAGE_NOTHING:
- return 0;
-
- case IMAGE_SUBWINDOW:
- /* #### implement me */
- return 0;
-
- default:
- abort ();
- return 0;
- }
- }
-
- unsigned short
- glyph_ascent (Lisp_Object glyph, face_index findex, int framep,
- Lisp_Object window)
- {
- return glyph_height_internal (glyph, findex, framep, window, RETURN_ASCENT);
- }
-
- unsigned short
- glyph_descent (Lisp_Object glyph, face_index findex, int framep,
- Lisp_Object window)
- {
- return glyph_height_internal (glyph, findex, framep, window, RETURN_DESCENT);
- }
-
- /* strictly a convenience function. */
- unsigned short
- glyph_height (Lisp_Object glyph, face_index findex, int framep,
- Lisp_Object window)
- {
- return glyph_height_internal (glyph, findex, framep, window, RETURN_HEIGHT);
- }
-
- DEFUN ("glyph-ascent", Fglyph_ascent, Sglyph_ascent, 1, 2, 0,
- "Return the ascent value of GLYPH on WINDOW.\n\
- This may not be exact as it does not take into account all of the context\n\
- that redisplay will.")
- (glyph, window)
- Lisp_Object glyph, window;
- {
- XSETWINDOW (window, decode_window (window));
- CHECK_GLYPH (glyph, 0);
-
- return (make_number (glyph_ascent (glyph, DEFAULT_INDEX, 0, window)));
- }
-
- DEFUN ("glyph-descent", Fglyph_descent, Sglyph_descent, 1, 2, 0,
- "Return the descent value of GLYPH on WINDOW.\n\
- This may not be exact as it does not take into account all of the context\n\
- that redisplay will.")
- (glyph, window)
- Lisp_Object glyph, window;
- {
- XSETWINDOW (window, decode_window (window));
- CHECK_GLYPH (glyph, 0);
-
- return (make_number (glyph_descent (glyph, DEFAULT_INDEX, 0, window)));
- }
-
- /* This is redundant but I bet a lot of people expect it to exist. */
- DEFUN ("glyph-height", Fglyph_height, Sglyph_height, 1, 2, 0,
- "Return the height of GLYPH on WINDOW.\n\
- This may not be exact as it does not take into account all of the context\n\
- that redisplay will.")
- (glyph, window)
- Lisp_Object glyph, window;
- {
- XSETWINDOW (window, decode_window (window));
- CHECK_GLYPH (glyph, 0);
-
- return (make_number (glyph_height (glyph, DEFAULT_INDEX, 0, window)));
- }
-
- #undef RETURN_ASCENT
- #undef RETURN_DESCENT
- #undef RETURN_HEIGHT
-
- /* #### do we need to cache this info to speed things up? */
-
- Lisp_Object
- glyph_baseline (Lisp_Object glyph, Lisp_Object domain)
- {
- if (!GLYPHP (glyph))
- return Qnil;
- else
- {
- Lisp_Object retval =
- specifier_instance_no_quit (GLYPH_BASELINE (XGLYPH (glyph)),
- domain, 0);
- if (!NILP (retval) && !INTP (retval))
- retval = Qnil;
- else if (INTP (retval))
- {
- if (XINT (retval) < 0)
- retval = Qzero;
- if (XINT (retval) > 100)
- retval = make_number (100);
- }
- return retval;
- }
- }
-
- Lisp_Object
- glyph_face (Lisp_Object glyph, Lisp_Object domain)
- {
- /* #### Domain parameter not currently used but it will be */
- if (!GLYPHP (glyph))
- return Qnil;
- else
- return GLYPH_FACE (XGLYPH (glyph));
- }
-
- int
- glyph_contrib_p (Lisp_Object glyph, Lisp_Object domain)
- {
- if (!GLYPHP (glyph))
- return 0;
- else
- return (!NILP (specifier_instance_no_quit
- (GLYPH_CONTRIB_P (XGLYPH (glyph)), domain, 0)));
- }
-
-
- /*****************************************************************************
- * glyph cache element functions *
- *****************************************************************************/
-
- /*
- #### All of this is 95% copied from face cache elements.
- Consider consolidating.
- #### We need to add a dirty flag to the glyphs.
- */
-
- void
- mark_glyph_cache_elements (glyph_cache_element_dynarr *elements,
- void (*markobj) (Lisp_Object))
- {
- int elt;
-
- if (!elements)
- return;
-
- for (elt = 0; elt < Dynarr_length (elements); elt++)
- {
- struct glyph_cache_element *inst = Dynarr_atp (elements, elt);
- ((markobj) (inst->glyph));
- }
- }
-
- static void
- update_glyph_cache_element_data (struct window *w, Lisp_Object glyph,
- struct glyph_cache_element *inst)
- {
- /* #### This should be || !inst->updated */
- if (NILP (inst->glyph) || !EQ (inst->glyph, glyph))
- {
- Lisp_Object window = Qnil;
-
- XSETWINDOW (window, w);
- inst->glyph = glyph;
-
- #define FROB(field) \
- do { \
- unsigned short new_val = glyph_##field (glyph, DEFAULT_INDEX, 0, window); \
- if (inst->field != new_val) \
- inst->field = new_val; \
- } while (0)
-
- /* #### This could be sped up if we redid things to grab the glyph
- instantiation and passed it to the size functions. */
- FROB (width);
- FROB (ascent);
- FROB (descent);
- #undef FROB
-
- }
-
- inst->updated = 1;
- }
-
- static void
- add_glyph_cache_element (struct window *w, Lisp_Object glyph)
- {
- struct glyph_cache_element new_inst;
-
- memset (&new_inst, 0, sizeof (struct glyph_cache_element));
- new_inst.glyph = Qnil;
-
- update_glyph_cache_element_data (w, glyph, &new_inst);
- Dynarr_add (w->glyph_cache_elements, new_inst);
- }
-
- static glyph_index
- get_glyph_cache_element_index (struct window *w, Lisp_Object glyph)
- {
- int elt;
-
- if (noninteractive)
- return 0;
-
- for (elt = 0; elt < Dynarr_length (w->glyph_cache_elements); elt++)
- {
- struct glyph_cache_element *inst =
- Dynarr_atp (w->glyph_cache_elements, elt);
-
- if (EQ (inst->glyph, glyph) && !NILP (glyph))
- {
- if (!inst->updated)
- update_glyph_cache_element_data (w, glyph, inst);
- return elt;
- }
- }
-
- /* If we didn't find the glyph, add it and then return its index. */
- add_glyph_cache_element (w, glyph);
- return elt;
- }
-
- void
- reset_glyph_cache_elements (struct window *w)
- {
- Dynarr_reset (w->glyph_cache_elements);
- get_glyph_cache_element_index (w, Vcontinuation_glyph);
- get_glyph_cache_element_index (w, Vtruncation_glyph);
- get_glyph_cache_element_index (w, Vhscroll_glyph);
- get_glyph_cache_element_index (w, Vcontrol_arrow_glyph);
- get_glyph_cache_element_index (w, Voctal_escape_glyph);
- get_glyph_cache_element_index (w, Vinvisible_text_glyph);
- }
-
- void
- mark_glyph_cache_elements_as_not_updated (struct window *w)
- {
- int elt;
-
- /* We need to have a dirty flag to tell if the glyph has changed.
- We can check to see if each glyph variable is actually a
- completely different glyph, though. */
- #define FROB(glyph_obj, gindex) \
- update_glyph_cache_element_data (w, glyph_obj, \
- Dynarr_atp (w->glyph_cache_elements, gindex))
-
- FROB (Vcontinuation_glyph, CONT_GLYPH_INDEX);
- FROB (Vtruncation_glyph, TRUN_GLYPH_INDEX);
- FROB (Vhscroll_glyph, HSCROLL_GLYPH_INDEX);
- FROB (Vcontrol_arrow_glyph, CONTROL_GLYPH_INDEX);
- FROB (Voctal_escape_glyph, OCT_ESC_GLYPH_INDEX);
- FROB (Vinvisible_text_glyph, INVIS_GLYPH_INDEX);
- #undef FROB
-
- for (elt = 0; elt < Dynarr_length (w->glyph_cache_elements); elt++)
- Dynarr_atp (w->glyph_cache_elements, elt)->updated = 0;
- }
-
-
- /*****************************************************************************
- * display tables *
- *****************************************************************************/
-
- /* Get the display table for use currently on window W with face FACE.
- Precedence:
-
- -- FACE's display table
- -- W's display table (comes from specifier `current-display-table')
-
- Ignore the specified tables if they are not valid;
- if no valid table is specified, return 0. */
-
- struct Lisp_Vector *
- get_display_table (struct window *w, face_index findex)
- {
- Lisp_Object tem = Qnil;
-
- tem = FACE_CACHE_ELEMENT_DISPLAY_TABLE (w, findex);
- if (VECTORP (tem) && XVECTOR (tem)->size == DISP_TABLE_SIZE)
- return XVECTOR (tem);
-
- tem = w->display_table;
- if (VECTORP (tem) && XVECTOR (tem)->size == DISP_TABLE_SIZE)
- return XVECTOR (tem);
-
- return 0;
- }
-
-
- /*****************************************************************************
- * initialization *
- *****************************************************************************/
-
- void
- syms_of_glyphs (void)
- {
- /* image instantiators */
-
- defsubr (&Simage_instantiator_type_list);
- defsubr (&Svalid_image_instantiator_type_p);
- defsubr (&Sset_device_type_image_conversion_list);
- defsubr (&Sdevice_type_image_conversion_list);
-
- defkeyword (&Q_file, ":file");
- defkeyword (&Q_data, ":data");
-
- /* image specifiers */
-
- defsubr (&Simage_specifier_p);
- defsymbol (&Qimage, "image");
-
- /* image instances */
-
- defsymbol (&Qimage_instancep, "image-instance-p");
- defsubr (&Smake_image_instance);
- defsubr (&Simage_instance_p);
- defsubr (&Simage_instance_type);
- defsubr (&Svalid_image_instance_type_p);
- defsubr (&Simage_instance_type_list);
- defsubr (&Simage_instance_name);
- defsubr (&Simage_instance_string);
- defsubr (&Simage_instance_file_name);
- defsubr (&Simage_instance_mask_file_name);
- defsubr (&Simage_instance_depth);
- defsubr (&Simage_instance_height);
- defsubr (&Simage_instance_width);
- defsubr (&Sset_image_instance_hotspot);
- defsubr (&Simage_instance_hotspot_x);
- defsubr (&Simage_instance_hotspot_y);
-
- /* Qnothing defined as part of the "nothing" image-instantiator
- type. */
- /* Qtext defined in general.c */
- defsymbol (&Qmono_pixmap, "mono-pixmap");
- defsymbol (&Qcolor_pixmap, "color-pixmap");
- defsymbol (&Qcursor, "cursor");
- defsymbol (&Qsubwindow, "subwindow");
-
- /* glyphs */
-
- defsymbol (&Qglyphp, "glyphp");
- defsymbol (&Qcontrib_p, "contrib-p");
- defsymbol (&Qbaseline, "baseline");
-
- defsubr (&Sglyph_type);
- defsubr (&Svalid_glyph_type_p);
- defsubr (&Sglyph_type_list);
- defsubr (&Sglyphp);
- defsubr (&Smake_glyph_internal);
- defsubr (&Sglyph_width);
- defsubr (&Sglyph_ascent);
- defsubr (&Sglyph_descent);
- defsubr (&Sglyph_height);
-
- /* Qbuffer defined in general.c. */
- /* Qcursor defined above */
- defsymbol (&Qicon, "icon");
- }
-
- void
- specifier_type_create_image (void)
- {
- /* image specifiers */
-
- INITIALIZE_SPECIFIER_TYPE_WITH_DATA (image, "image", "imagep");
-
- SPECIFIER_HAS_METHOD (image, create);
- SPECIFIER_HAS_METHOD (image, mark);
- SPECIFIER_HAS_METHOD (image, instantiate);
- SPECIFIER_HAS_METHOD (image, validate);
- SPECIFIER_HAS_METHOD (image, after_change);
- SPECIFIER_HAS_METHOD (image, going_to_add);
- }
-
- void
- image_instantiator_type_create (void)
- {
- /* image instantiators */
-
- the_image_instantiator_type_entry_dynarr =
- Dynarr_new (struct image_instantiator_type_entry);
-
- Vimage_instantiator_type_list = Qnil;
- staticpro (&Vimage_instantiator_type_list);
-
- INITIALIZE_IMAGE_INSTANTIATOR_TYPE (nothing, "nothing");
-
- IITYPE_HAS_METHOD (nothing, instantiate);
-
- INITIALIZE_IMAGE_INSTANTIATOR_TYPE (string, "string");
-
- IITYPE_HAS_METHOD (string, validate);
- IITYPE_HAS_METHOD (string, instantiate);
-
- IITYPE_VALID_KEYWORD (string, Q_data, valid_string_p);
-
- INITIALIZE_IMAGE_INSTANTIATOR_TYPE (formatted_string, "formatted-string");
-
- IITYPE_HAS_METHOD (formatted_string, validate);
- IITYPE_HAS_METHOD (formatted_string, instantiate);
-
- IITYPE_VALID_KEYWORD (formatted_string, Q_data, valid_string_p);
- }
-
- void
- vars_of_glyphs (void)
- {
- Vthe_nothing_vector = vector1 (Qnothing);
- staticpro (&Vthe_nothing_vector);
-
- /* image instances */
-
- Vimage_instance_type_list = list6 (Qnothing, Qtext, Qmono_pixmap,
- Qcolor_pixmap, Qcursor, Qsubwindow);
- staticpro (&Vimage_instance_type_list);
-
- /* glyphs */
-
- Vglyph_type_list = list3 (Qbuffer, Qcursor, Qicon);
- staticpro (&Vglyph_type_list);
-
- /* The octal-escape glyph, control-arrow-glyph and
- invisible-text-glyph are completely initialized in glyphs.el */
-
- DEFVAR_LISP ("octal-escape-glyph", &Voctal_escape_glyph,
- "What to prefix character codes displayed in octal with.");
- Voctal_escape_glyph = Qnil;
-
- DEFVAR_LISP ("control-arrow-glyph", &Vcontrol_arrow_glyph,
- "What to use as an arrow for control characters.");
- Vcontrol_arrow_glyph = Qnil;
-
- DEFVAR_LISP ("invisible-text-glyph", &Vinvisible_text_glyph,
- "What to use to indicate the presence of invisible text.");
- Vinvisible_text_glyph = Qnil;
-
- /* Partially initialized in glyphs.el */
- DEFVAR_LISP ("hscroll-glyph", &Vhscroll_glyph,
- "What to display at the beginning of horizontally scrolled lines.");
- Vhscroll_glyph = Qnil;
- }
-
- void
- specifier_vars_of_glyphs (void)
- {
- /* display tables */
-
- DEFVAR_SPECIFIER ("current-display-table", &Vcurrent_display_table,
- "*The display table currently in use.\n\
- This is a specifier; use `set-specifier' to change it.\n\
- The display table is a vector created with `make-display-table'.\n\
- The 256 elements control how to display each possible text character.\n\
- Each value should be a string, a glyph, a vector or nil.\n\
- If a value is a vector it must be composed only of strings and glyphs.\n\
- nil means display the character in the default fashion.\n\
- Faces can have their own, overriding display table.");
- Vcurrent_display_table = Fmake_specifier (Qgeneric);
- set_specifier_fallback (Vcurrent_display_table,
- list1 (Fcons (Qnil, Qnil)));
- set_specifier_caching (Vcurrent_display_table,
- slot_offset (struct window,
- display_table),
- some_window_value_changed,
- 0, 0);
- }
-
- void
- complex_vars_of_glyphs (void)
- {
- /* Partially initialized in glyphs-x.c, glyphs.el */
- DEFVAR_LISP ("truncation-glyph", &Vtruncation_glyph,
- "What to display at the end of truncated lines.");
- Vtruncation_glyph = Fmake_glyph_internal (Qbuffer);
-
- /* Partially initialized in glyphs-x.c, glyphs.el */
- DEFVAR_LISP ("continuation-glyph", &Vcontinuation_glyph,
- "What to display at the end of wrapped lines.");
- Vcontinuation_glyph = Fmake_glyph_internal (Qbuffer);
-
- /* Partially initialized in glyphs-x.c, glyphs.el */
- DEFVAR_LISP ("xemacs-logo", &Vxemacs_logo,
- "The glyph used to display the XEmacs logo at startup.");
- Vxemacs_logo = Fmake_glyph_internal (Qbuffer);
- }
-
-
-